﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using PayexpDAL;
using Utilities;
using System.Globalization;

namespace Moneymatters.UserControls
{
    public partial class FilterControl : UserControl
    {
        public FilterControl()
        {
            InitializeComponent();
        }

        private void linkLabelFirstHeadDetailsFilter_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            SetHeadDetailsFilter(labelFirstHeadDetailsFilter);
        }

        private void linkLabelSecondHeadDetailsFilter_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            if (string.IsNullOrEmpty(labelFirstHeadDetailsFilter.Text.Trim()))
            {
                SetHeadDetailsFilter(labelFirstHeadDetailsFilter);
            }
            else
            {
                SetHeadDetailsFilter(labelSecondHeadDetailsFilter);
            }
        }

        private void linkLabelThirdHeadDetailsFilter_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            if (string.IsNullOrEmpty(labelFirstHeadDetailsFilter.Text.Trim()))
            {
                SetHeadDetailsFilter(labelFirstHeadDetailsFilter);
            }
            else if (string.IsNullOrEmpty(labelSecondHeadDetailsFilter.Text.Trim()))
            {
                SetHeadDetailsFilter(labelSecondHeadDetailsFilter);
            }
            else
            {
                SetHeadDetailsFilter(labelThirdHeadDetailsFilter);
            }
        }

        private void SetHeadDetailsFilter(Label headDetailsLabelToSet)
        {
            TransactionTypeTreeViewForm form = new TransactionTypeTreeViewForm(false, true);
            form.CreateTreeView(new List<string>());

            DialogResult dr = form.ShowDialog();

            while (dr == System.Windows.Forms.DialogResult.OK && form.GetSelectedTransactionTypes().Count == 0)
            {
                MessageBox.Show("Please choose a valid head (other than the root) to add sub heads.", "Choose valid head", MessageBoxButtons.OK, MessageBoxIcon.Information);
                dr = form.ShowDialog();
            }

            if (dr == System.Windows.Forms.DialogResult.OK)
            {
                headDetailsLabelToSet.Text = form.GetSelectedShortText();
                headDetailsLabelToSet.Tag = form.GetSelectedTransactionTypes();
            }
        }

        private void checkBoxDateFilter_CheckedChanged(object sender, EventArgs e)
        {
            this.groupBoxDateFilters.Enabled = this.checkBoxDateFilter.Checked;
        }

        private void checkBoxAmountRangeFilter_CheckedChanged(object sender, EventArgs e)
        {
            this.groupBoxAmountRangeFilters.Enabled = this.checkBoxAmountRangeFilter.Checked;
        }

        private void checkBoxChequeNumberRangeFilter_CheckedChanged(object sender, EventArgs e)
        {
            this.groupBoxChequeNumberRangeFilters.Enabled = this.checkBoxChequeNumberRangeFilter.Checked;
        }

        private void checkBoxHeadDetailsFilter_CheckedChanged(object sender, EventArgs e)
        {
            this.groupBoxHeadDetailsFilters.Enabled = this.checkBoxHeadDetailsFilter.Checked;
        }

        private void checkBoxNarrationFilter_CheckedChanged(object sender, EventArgs e)
        {
            this.groupBoxNarrationFilters.Enabled = this.checkBoxNarrationFilter.Checked;
            if (this.checkBoxNarrationFilter.Checked)
            {
                this.textBoxNarrationFilter.Focus();
                this.textBoxNarrationFilter.Select(0, 0);
            }
        }

        private void buttonClearFilterHeads_Click(object sender, EventArgs e)
        {
            this.labelFirstHeadDetailsFilter.Text = string.Empty;
            this.labelSecondHeadDetailsFilter.Text = string.Empty;
            this.labelThirdHeadDetailsFilter.Text = string.Empty;
        }

        private void radioBtnTransactionDateFilter_CheckedChanged(object sender, EventArgs e)
        {
            this.radioBtnBankDateFilter.Checked = !this.radioBtnTransactionDateFilter.Checked;
        }

        private void radioBtnBankDateFilter_CheckedChanged(object sender, EventArgs e)
        {
            this.radioBtnTransactionDateFilter.Checked = !this.radioBtnBankDateFilter.Checked;
        }

        private List<string> PerformFilterCriteriaValidation(FilterCriteria filterCriteria)
        {
            List<string> messages = new List<string>();

            #region date range validation
            if (this.checkBoxDateFilter.Checked)
            {
                bool hasDateError = false;
                if (this.dateTimePickerTxnDateFromFilter.Value.CompareTo(this.dateTimePickerTxnDateToFilter.Value) > 0)
                {
                    messages.Add("From Date cannot be greater than To Date.");
                    hasDateError = true;
                }

                if (filterCriteria.LimitTheNumberOfRecords)
                {
                    int maxDateRangeAllowed = int.Parse(AppSettingsLoader.AppSettingsValuesMap[Constants.AppSettingsKeys.MaxDateRangeInDays]);
                    if (this.dateTimePickerTxnDateToFilter.Value.Subtract(this.dateTimePickerTxnDateFromFilter.Value).TotalDays > (maxDateRangeAllowed - 1))
                    {
                        messages.Add(string.Format("Please limit your date range to {0} days inclusive of the 'From' and 'To' dates.", maxDateRangeAllowed));
                        hasDateError = true;
                    }
                }

                if (this.dateTimePickerTxnDateFromFilter.Value.CompareTo(DateTime.Today) > 0 ||
                         this.dateTimePickerTxnDateToFilter.Value.CompareTo(DateTime.Today) > 0)
                {
                    messages.Add("Please check the selected transaction dates. They cannot be later than today's date.");
                    hasDateError = true;
                }


                if (!hasDateError)
                {
                    filterCriteria.DateFrom = this.dateTimePickerTxnDateFromFilter.Value;

                    filterCriteria.DateTo = this.dateTimePickerTxnDateToFilter.Value;

                    filterCriteria.DateTo = filterCriteria.DateTo.Value.Add(new TimeSpan(0, 23, 59, 59, 999));

                    filterCriteria.TransactionDateSelected = this.radioBtnTransactionDateFilter.Checked;

                    // set the bank accounts id
                    if (!filterCriteria.TransactionDateSelected)
                    {
                        ComboBoxItem selectedItem = (ComboBoxItem)this.comboBoxBankAccountsFilter.SelectedItem;
                        BankAccount selectedBankAccountFilter = (BankAccount)selectedItem.Value;
                        filterCriteria.BankAccountsId = selectedBankAccountFilter.Id;
                        filterCriteria.BankDisplayName = selectedBankAccountFilter.BankDisplayName;
                    }
                }

                // if date range is given...then we do not have to worry about the number of records
                filterCriteria.PageNumber = null;
                filterCriteria.NumberOfRecords = null;
            }
            #endregion date range validation

            #region amount range validation
            if (this.checkBoxAmountRangeFilter.Checked)
            {
                bool hasAmountRangeError = false;

                NumberFormatInfo nfiForAmount = new NumberFormatInfo(); // just two decimal places
                nfiForAmount.NumberDecimalDigits = 2;

                // From amount
                decimal transAmountValueFrom = 0;
                try
                {
                    decimal.TryParse(this.textBoxAmountFromFilter.Text.Trim(),
                                         NumberStyles.AllowDecimalPoint, nfiForAmount,
                                         out transAmountValueFrom);
                    if (transAmountValueFrom <= 0 || Utils.CountDecimalPlaces(transAmountValueFrom) > 2)
                    {
                        messages.Add("Please enter a valid value for amount in the 'From' field. All amount values should be non-negative and can have only 2 digits after the decimal.");
                        hasAmountRangeError = true;
                    }
                }
                catch
                {
                    messages.Add("Please enter a valid value for amount in the 'From' field. All amount values should be non-negative and can have only 2 digits after the decimal.");
                    hasAmountRangeError = true;
                }

                // To amount
                decimal transAmountValueTo = 0;
                try
                {
                    decimal.TryParse(this.textBoxAmountToFilter.Text.Trim(),
                                         NumberStyles.AllowDecimalPoint, nfiForAmount,
                                         out transAmountValueTo);
                    if (transAmountValueTo <= 0 || Utils.CountDecimalPlaces(transAmountValueTo) > 2)
                    {
                        messages.Add("Please enter a valid value for amount in the 'To' field. All amount values should be non-negative and can have only 2 digits after the decimal.");
                        hasAmountRangeError = true;
                    }
                }
                catch
                {
                    messages.Add("Please enter a valid value for amount in the 'To' field. All amount values should be non-negative and can have only 2 digits after the decimal.");
                    hasAmountRangeError = true;
                }

                if (transAmountValueFrom > transAmountValueTo)
                {
                    messages.Add("'From' amount value cannot be greater than 'To' amount value.");
                    hasAmountRangeError = true;
                }

                if (!hasAmountRangeError)
                {
                    filterCriteria.AmountFrom = transAmountValueFrom;
                    filterCriteria.AmountTo = transAmountValueTo;
                }
            }
            #endregion amount range validation

            #region cheque number validation
            if (this.checkBoxChequeNumberRangeFilter.Checked)
            {
                bool hasChequeNumberRangeError = false;

                int chequeNumberFrom = 0;
                int chequeNumberTo = 0;

                int.TryParse(this.textBoxChequeNumberFromFilter.Text.Trim(), out chequeNumberFrom);
                if (chequeNumberFrom == 0)
                {
                    messages.Add("Please enter a valid cheque number in the 'From' field");
                    hasChequeNumberRangeError = true;
                }

                int.TryParse(this.textBoxChequeNumberToFilter.Text.Trim(), out chequeNumberTo);
                if (chequeNumberTo == 0)
                {
                    messages.Add("Please enter a valid cheque number in the 'To' field");
                    hasChequeNumberRangeError = true;
                }

                if (chequeNumberFrom > chequeNumberTo)
                {
                    messages.Add("Cheque number in the 'From' field cannot be greater than the cheque number in the 'To' field.");
                    hasChequeNumberRangeError = true;
                }

                if (!hasChequeNumberRangeError)
                {
                    filterCriteria.ChequeNumberFrom = chequeNumberFrom;
                    filterCriteria.ChequeNumberTo = chequeNumberTo;
                }

            }
            #endregion cheque number validation

            #region head details validation
            if (this.checkBoxHeadDetailsFilter.Checked)
            {
                if (string.IsNullOrEmpty(this.labelFirstHeadDetailsFilter.Text.Trim()) &&
                string.IsNullOrEmpty(this.labelSecondHeadDetailsFilter.Text.Trim()) &&
                string.IsNullOrEmpty(this.labelThirdHeadDetailsFilter.Text.Trim()))
                {
                    messages.Add("Please select at least one 'head details'.");
                }
                else
                {
                    if (!string.IsNullOrEmpty(this.labelFirstHeadDetailsFilter.Text.Trim()) && this.labelFirstHeadDetailsFilter.Tag != null)
                    {
                        List<TransactionType> hierarchy = (List<TransactionType>)this.labelFirstHeadDetailsFilter.Tag;
                        filterCriteria.FirstHeadDetailsId = hierarchy.Last().Id;
                        filterCriteria.FirstHeadDetailsHierarchy = hierarchy;
                        //TransactionType firstHead = (TransactionType)this.labelFirstHeadDetailsFilter.Tag;
                        //filterCriteria.FirstHeadDetailsId = firstHead.Id;
                    }

                    if (!string.IsNullOrEmpty(this.labelSecondHeadDetailsFilter.Text.Trim()) && this.labelSecondHeadDetailsFilter.Tag != null)
                    {
                        List<TransactionType> hierarchy = (List<TransactionType>)this.labelSecondHeadDetailsFilter.Tag;
                        filterCriteria.SecondHeadDetailsId = hierarchy.Last().Id;
                        filterCriteria.SecondHeadDetailsHierarchy = hierarchy;

                        //TransactionType secondHead = (TransactionType)this.labelSecondHeadDetailsFilter.Tag;
                        //filterCriteria.SecondHeadDetailsId = secondHead.Id;
                    }

                    if (!string.IsNullOrEmpty(this.labelThirdHeadDetailsFilter.Text.Trim()) && this.labelThirdHeadDetailsFilter.Tag != null)
                    {
                        List<TransactionType> hierarchy = (List<TransactionType>)this.labelThirdHeadDetailsFilter.Tag;
                        filterCriteria.ThirdHeadDetailsId = hierarchy.Last().Id;
                        filterCriteria.ThirdHeadDetailsHierarchy = hierarchy;

                        //TransactionType thirdHead = (TransactionType)this.labelThirdHeadDetailsFilter.Tag;
                        //filterCriteria.ThirdHeadDetailsId = thirdHead.Id;
                    }

                }
            }
            #endregion head details validation

            #region narration validation

            if (this.checkBoxNarrationFilter.Checked)
            {
                if (string.IsNullOrEmpty(this.textBoxNarrationFilter.Text.Trim()))
                {
                    messages.Add("Please either enter a narration text to look for or uncheck the narration filter.");
                }
                else
                {
                    filterCriteria.Narration = this.textBoxNarrationFilter.Text.Trim().Replace(Environment.NewLine, string.Empty);
                }
            }

            #endregion narration validation

            return messages;

        }
    }
}
